package com.xhui.vimarket.zkplus.zul.attr;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import lombok.Getter;
import lombok.Setter;

import org.slf4j.Logger;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Components;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.IdSpace;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zul.Div;
import org.zkoss.zul.Popup;
import org.zkoss.zul.Radio;
import org.zkoss.zul.Toolbarbutton;
import org.zkoss.zul.Window;

import com.xhui.vimarket.common.Constants;
import com.xhui.vimarket.common.utils.vo.RetVO;
import com.xhui.vimarket.zkplus.callback.EvtCallback;
import com.xhui.vimarket.zkplus.zul.attr.ada.AttrAda;
import com.xhui.vimarket.zkplus.zul.attr.ada.AttrExecListener;
import com.xhui.vimarket.zkplus.zul.attr.ada.impl.DefaultAttrAda;
import com.xhui.vimarket.zkplus.zul.attr.bean.AttrInst;
import com.xhui.vimarket.zkplus.zul.attr.bean.AttrInstFactory;
import com.xhui.vimarket.zkplus.zul.attr.bean.AttrTmpl;
import com.xhui.vimarket.zkplus.zul.attr.bean.AttrWind;
import com.xhui.vimarket.zkplus.zul.attr.bean.EvtData;
import com.xhui.vimarket.zkplus.zul.attr.bean.impl.AttrInstFactoryImpl;
import com.xhui.vimarket.zkplus.zul.attr.bus.AttrBus;
import com.xhui.vimarket.zkplus.zul.attr.bus.impl.AttrBusImpl;
import com.xhui.vimarket.zkplus.zul.attr.mod.AttrCompConstants;
import com.xhui.vimarket.zkplus.zul.attr.mod.AttrCompFactory;
import com.xhui.vimarket.zkplus.zul.attr.mod.AttrCompUtil;

/**
 * @版权：福富软件 版权所有 (c) 2010
 * @文件：com.zkplus.zul.attr.AttrExt.java
 * @所含类：
 * @author: wuyx
 * @version: V1.0
 * @see:
 * @创建日期：2010-12-14
 * @功能说明：属性控件
 * @修改记录： =============================================================<br>
 *        日期:2010-12-14 创建
 *        =============================================================<br>
 */
public class AttrExt extends Window implements IdSpace {
    
    /**
     * serialVersionUID.
     */
    private static final long           serialVersionUID  = -8006322642378758495L;
    /**
     * 子属性变更事件.
     */
    public static final String          ON_SUB_CHANGE     = "onSubChange";
    /**
     * 日志.
     */
    private static Logger               logger            = Logger.getLogger(AttrExt.class);
    /**
     * zul模板.
     */
    private final String                zulTmpl           = "/public/zul/comp/attr_box.zul";
    /**
     * attrAda.
     */
    @Getter
    private AttrAda                     attrAda           = DefaultAttrAda.instance();
    /**
     * 属性窗口.
     */
    @Getter
    private Window                      attrWin;
    /**
     * 属性容器.
     */
    @Getter
    private final Div                   attrContainer;
    /**
     * 窗口展示规格模板.
     */
    @Getter
    @Setter
    private AttrWind                    attrSpec;
    /**
     * 初始值实例值列表.
     */
    private List<AttrInst>              initAttrInstList  = new ArrayList<AttrInst>();
    /**
     * 预留，分组ID.
     */
    private int                         groupId           = 1;
    /**
     * 界面序列化StringBuffer.
     */
    private final StringBuffer          innerComp         = new StringBuffer();
    /**
     * 实例数据工厂树.
     */
    private AttrInstFactory             attrInstFactory   = new AttrInstFactoryImpl();
    /**
     * 实例历史操作列表.
     */
    private final List<AttrInst>        attrInstHisList   = new ArrayList<AttrInst>();
    /**
     * 上次实例值记录.
     */
    private final Map<Object, AttrInst> attrInstHisMap    = new HashMap<Object, AttrInst>();
    
    /**
     * 刷新监听.
     */
    private Map<String, EvtCallback>    refreshEvtCallback;
    /**
     * 是否自动上次实例值记录，默认记录.
     */
    @Getter
    @Setter
    private boolean                     isOpHisAutoCommit = true;
    
    /**
     * 工具栏是否可见.
     */
    @Getter
    @Setter
    private boolean                     toolboxVisible    = false;
    /**
     * 是否配置预览.
     */
    @Getter
    private boolean                     settingPreview    = false;
    /**
     * 工具栏.
     */
    @Getter
    @Setter
    private Popup                       toolbar;
    /**
     * 当前处理工具栏.
     */
    @Getter
    @Setter
    private Toolbarbutton               curToolbarbutton;
    
    /**
     * entity.
     */
    @Getter
    @Setter
    private Object                      entity;
    
    /**
     * 信息全列表.
     */
    @Setter
    @Getter
    public Map                          attrViewMap       = new HashMap<String, Integer>(0);
    
    /**
     * attrBus.
     */
    private AttrBus                     attrBus           = null;
    
    /**
     * .
     */
    @Getter
    private Div                         plugbox           = null;
    
    public AttrInstFactory getAttrInstFactory() {
        return this.attrInstFactory;
    }
    
    public void setAttrInstFactory(final AttrInstFactory attrInstFactory) {
        this.attrInstFactory = attrInstFactory;
    }
    
    /**
     * 构造函数.
     */
    public AttrExt() {
        // 1. Render the template
        Executions.createComponents(this.zulTmpl, this, null);
        // 2. Wire variables (optional)
        Components.wireVariables(this, this);
        // 3. Wire event listeners (optional)
        Components.addForwards(this, this, '$');
        this.attrContainer = (Div) this.attrWin.getFellow("attrContainer");
        this.toolbar = (Popup) this.attrWin.getFellow("toolbar");
        this.plugbox = (Div) this.attrWin.getFellow("plugbox");
    }
    
    /**
     * 初始化.
     */
    public void onCreate() {
        AttrExt.logger.debug("onCreate");
    }
    
    public List<AttrInst> getInitAttrInstList() {
        return this.initAttrInstList;
    }
    
    /**
     * 根据规格页面数据展示界面.
     */
    public void display() {
        if (AttrExt.logger.isDebugEnabled()) {
            logger.debug("attr ext begin:" + System.currentTimeMillis());
        }
        AttrCompFactory.getInst(this.attrSpec.getAttrTmpl().getDisplayMode()).create(this,
            this.attrSpec.getAttrTmpl(), this.attrContainer);
        if (AttrExt.logger.isDebugEnabled()) {
            AttrExt.logger.debug(this.innerComp.toString());
            logger.debug("attr ext end:" + System.currentTimeMillis());
        }
        
    }
    
    /**
     * 清空展示界面.
     */
    @SuppressWarnings("unchecked")
    public void cleanDisplay() {
        final List<Component> list = this.attrContainer.getChildren();
        if (list != null) {
            final int sum = list == null ? 0
                : list.size();
            for (int i = sum - 1; i >= 0; i--) {
                final Component comp = list.get(i);
                this.attrContainer.removeChild(comp);
            }
        }
    }
    
    /**
     * 刷新展示界面.
     */
    public void refreshDisplay() {
        this.cleanDisplay();
        this.display();
    }
    
    /**
     * 赋值实例数据.
     * 
     * @param attrList
     *            实例数据
     */
    public void setAttrInst(final List<AttrInst> attrList) {
        this.setAttrInst(attrList, false);
    }
    
    /**
     * 设置是否预览.
     * 
     * @param settingPreview boolean
     */
    public void setSettingPreview(final boolean settingPreview) {
        this.settingPreview = settingPreview;
        if (this.attrAda != null) {
            this.attrAda.setSettingPreview(settingPreview);
        }
    }
    
    /**
     * 设置控件适配器.
     * 
     * @param attrAda AttrAda
     */
    public void setAttrAda(final AttrAda attrAda) {
        this.attrAda = attrAda;
        this.attrAda.setSettingPreview(this.isSettingPreview());
    }
    
    /**
     * 赋值实例数据.
     * 
     * @param attrList
     *            实例数据
     * @param isDefault
     *            是否设为初始值
     */
    public void setAttrInst(final List<AttrInst> attrList, final boolean isDefault) {
        AttrExt.logger.debug("setAttrInst");
        final Component comp = this.attrContainer.getFirstChild();
        AttrCompFactory.getInstByComponent(comp).setValue(this, comp, attrList, attrViewMap);
        // 初始值
        if (isDefault && attrList != null) {
            this.initAttrInstList = attrList;
            // 加入历史库
        }
        // 展示非空
        AttrCompFactory.getInstByComponent(comp).signRuleHint(this, comp);
    }
    
    /**
     * 赋值删除实例数据.
     * 
     * @param attrList
     *            实例数据
     */
    public void setRemovedAttrInst(final List<AttrInst> attrList) {
        final Component comp = this.attrContainer.getFirstChild();
        AttrCompFactory.getInstByComponent(comp).setRemovedValue(this, comp, attrList);
    }
    
    /**
     * 赋值不允许采集实例数据.
     * 
     * @param attrList
     *            实例数据
     */
    public void setDisabledAttrInst(final List<AttrInst> attrList) {
        final Component comp = this.attrContainer.getFirstChild();
        AttrCompFactory.getInstByComponent(comp).setDisabledValue(this, comp, attrList);
    }
    
    /**
     * 获取实例数据.
     * 
     * @return void
     */
    public ArrayList<AttrInst> getAttrInst() {
        ArrayList<AttrInst> retList = null;
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            retList = AttrCompFactory.getInstByComponent(comp).getValue(this, comp);
        }
        return retList;
    }
    
    /**
     * 判断规则.
     * 
     * @return void
     */
    public RetVO validate() {
        RetVO retVo = new RetVO();
        retVo.setResult(Constants.RET_TRUE);
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            List<RetVO> retList = AttrCompFactory.getInstByComponent(comp).validate(this, comp);
            if (retList != null) {
                for (final RetVO subVo : retList) {
                    if (AttrCompConstants.RET_ERROR.equals(subVo.getResult())
                        || AttrCompConstants.RET_SELECT.equals(subVo.getResult())) {
                        retVo.setResult(Constants.RET_FALSE);
                        break;
                    }
                }
            }
            retVo.setDataList(retList);
        }
        return retVo;
    }
    
    /**
     * 获取实例数据.
     * 
     * @param attrId
     *            long
     * @return void
     */
    public List<Component> getAttrComp(final long attrId) {
        List<Component> retList = null;
        AttrExt.logger.debug("getAttrComp");
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            retList = AttrCompFactory.getInstByComponent(comp).getComp(this, comp, attrId);
        }
        return retList;
    }
    
    /**
     * 获取实例数据.
     * 
     * @param javaCode
     *            String
     * @return void
     */
    public List<Component> getAttrCompByCode(final String javaCode) {
        List<Component> retList = null;
        AttrExt.logger.debug("getAttrComp");
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            retList = AttrCompFactory.getInstByComponent(comp).getComp(this, comp, javaCode);
        }
        return retList;
    }
    
    /**
     * 获取所有空实例数据.
     * 
     * @return void
     */
    public ArrayList<AttrInst> getAllNullAttrInst() {
        ArrayList<AttrInst> retList = null;
        AttrExt.logger.debug("getAllNullAttrInst");
        if (this.attrSpec.getAttrTmpl() != null) {
            retList = AttrCompFactory.getInst(this.attrSpec.getAttrTmpl().getDisplayMode())
                .getNullValue(this, this.attrSpec.getAttrTmpl());
        }
        return retList;
    }
    
    /**
     * 获取实例数据.
     */
    public void clean() {
        AttrExt.logger.debug("clean");
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            AttrCompFactory.getInstByComponent(comp).clean(this, comp);
        }
    }
    
    /**
     * 根据初始值重置实例数据.
     */
    public void reset() {
        AttrExt.logger.debug("reset");
        this.clean();
        this.setAttrInst(this.initAttrInstList);
    }
    
    /**
     * 设置不可编辑.
     */
    public void setDisabled() {
        this.setDisabled(true);
    }
    
    /**
     * 设置不可编辑.
     * 
     * @param tflag
     *            boolean
     */
    public void setDisabled(final boolean tflag) {
        AttrExt.logger.debug("setDisabled");
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            AttrCompFactory.getInstByComponent(comp).setDisabled(this, comp, tflag);
        }
    }
    
    /**
     * 生成实例数据对象.
     * 
     * @return AttrInst
     */
    public AttrInst newAttrInst() {
        return this.attrInstFactory.newAttrInst();
    }
    
    /**
     * 生成实例数据对象log.
     * 
     * @param str
     *            组件标签
     */
    public void appendInnerComp(final String str) {
        this.innerComp.append(str);
    }
    
    /**
     * 生成实例数据对象属性log.
     * 
     * @param key
     *            客户化标签key
     * @param val
     *            客户化数据值
     */
    public void appendInnerCompAttr(final String key, final String val) {
        this.innerComp.append("<custom-attributes ");
        this.innerComp.append(key);
        this.innerComp.append("=\"");
        this.innerComp.append(val);
        this.innerComp.append("\"/>");
    }
    
    /**
     * 获取多实例分组ID.
     * 
     * @return int
     */
    public int getGroupId() {
        return ++this.groupId;
    }
    
    /**
     * 子控件变更事件触发.
     * 
     * @param evtData
     *            EvtData {attrComp 控件,
     *            旧值 暂定，无法获取,
     *            oldVal 新值}
     */
    public void onSubChange(final EvtData evtData) {
        if (AttrExt.logger.isDebugEnabled()) {
            AttrExt.logger.debug(evtData.getAttrComp() + "");
            AttrExt.logger.debug(evtData.getNewVal() + "");
            AttrExt.logger.debug(evtData.getOldVal() + "");
            AttrExt.logger.debug(evtData.getAttrId() + "");
            AttrExt.logger.debug(evtData.getOp() + "");
        }
        // 发送事件
        final Event evt = new Event(AttrExt.ON_SUB_CHANGE, this, evtData);
        Events.sendEvent(this, evt);
        // 自动将操作入历史库
        if (this.isOpHisAutoCommit) {
            this.commitSubChangeToHis(evtData);
        }
    }
    
    /**
     * 子控件变更事件触发,确认有效，记录到操作历史中.
     * 
     * @param evtData
     *            EvtData {attrComp 控件,
     *            旧值 暂定，无法获取,
     *            oldVal 新值}
     */
    public void commitSubChangeToHis(final EvtData evtData) {
        if (evtData == null) {
            // throw ex TODO
        } else if (AttrCompConstants.OP_REMOVE.equals(evtData.getOp())) { // del
            this.attrInstHisMap.remove(evtData.getAttrId());
        } else if (AttrCompConstants.OP_ADD.equals(evtData.getOp())
            || AttrCompConstants.OP_MOD.equals(evtData.getOp())) { // update
            if (evtData.getNewVal() != null) {
                this.attrInstHisMap.put(evtData.getNewVal().getAttrId(), evtData.getNewVal());
            } else if (evtData.getNewValList() != null && evtData.getNewValList().size() > 0) { // 多实例
                this.attrInstHisMap.put(evtData.getNewValList().get(0).getAttrId(), evtData
                    .getNewVal());
            }
        }
    }
    
    /**
     * 根据值更新上次数据.
     * 
     * @param attrComp
     *            控件
     */
    public void refreshAttrComp(final Component attrComp) {
        final long attrId = AttrCompUtil.getAttrCompAttrId(attrComp);
        if (attrId > 0) {
            final Object oAttrInst = this.attrInstHisMap.get(attrId);
            if (oAttrInst == null) { // 上次为空值,清空
                AttrCompFactory.getInstByComponent(attrComp).clean(this, attrComp);
            } else { // 设置为上次值
                final ArrayList<AttrInst> attrInstList = new ArrayList<AttrInst>(1);
                attrInstList.add((AttrInst) oAttrInst);
                AttrCompFactory.getInstByComponent(attrComp).setValue(this, attrComp, attrInstList,
                    attrViewMap);
            }
        } else {
            // throw ex TODO
        }
    }
    
    /**
     * 工具栏点击按钮事件.
     * 
     * @param evt Event
     * @author wuyx
     * 2011-3-1 wuyx 
     */
    public void onToolClick$attrWin(final Event evt) {
        // 点击按钮
        this.curToolbarbutton = (Toolbarbutton) ((ForwardEvent) ((ForwardEvent) evt).getOrigin())
            .getOrigin().getTarget();
        this.setToolbarRadio(this.curToolbarbutton.getAttribute(Constants.COMMON_OP_TAG) + "");
        this.toolbar.open(this.attrWin);
    }
    
    /**
     * 工具栏点击按钮事件.
     * 
     * @param evt Event
     * @author wuyx
     * 2011-3-1 wuyx 
     */
    public void onToolClick(Toolbarbutton icurToolbarbutton) {
        // 点击按钮
        this.curToolbarbutton = icurToolbarbutton;
        this.setToolbarRadio(this.curToolbarbutton.getAttribute(Constants.COMMON_OP_TAG) + "");
        this.toolbar.open(this.attrWin);
    }
    
    /**
     * setToolbarRadio.
     * 
     * @param op String
     * @author wuyx
     * 2011-3-1 wuyx 
     */
    public void setToolbarRadio(final String op) {
        if (Constants.COMMON_OP_DELETE.equals(op)) {
            ((Radio) this.attrWin.getFellow("tbarUpdateBtn")).setChecked(false);
            ((Radio) this.attrWin.getFellow("tbarDeleteBtn")).setChecked(true);
        } else {
            ((Radio) this.attrWin.getFellow("tbarUpdateBtn")).setChecked(true);
            ((Radio) this.attrWin.getFellow("tbarDeleteBtn")).setChecked(false);
        }
    }
    
    /**
     * setToolbarAttr.
     * 
     * @param evt Event
     * @author wuyx
     * 2011-3-1 wuyx 
     */
    public void onToolbarSetAttr$attrWin(final Event evt) {
        if (((Radio) this.attrWin.getFellow("tbarUpdateBtn")).isChecked()) {
            this.curToolbarbutton.setAttribute(Constants.COMMON_OP_TAG, Constants.COMMON_OP_UPDATE);
        } else {
            this.curToolbarbutton.setAttribute(Constants.COMMON_OP_TAG, Constants.COMMON_OP_DELETE);
        }
    }
    
    /**
     * 获取实例数据.
     * 
     * @param attrExecListener AttrExecListener
     */
    public void exec(final AttrExecListener attrExecListener) {
        final List<Component> compList = this.attrContainer.getChildren();
        if (compList != null) {
            for (Component comp : compList) {
                if (comp != null) {
                    AttrCompFactory.getInstByComponent(comp).exec(this, comp, attrExecListener);
                }
            }
        }
        // final Component comp = this.attrContainer.getFirstChild();
    }
    
    /**
     * 根据类型和code获取指定的模板配置.
     * 
     * @param displayType String
     * @param javaCode String
     * @return void
     */
    public AttrTmpl getAttrTmplByTypeCode(final String displayType, final String javaCode) {
        if (this.attrSpec.getAttrTmpl() != null) {
            if (("" + displayType).equals(this.attrSpec.getAttrTmpl().getDisplayMode())
                && ("" + javaCode).equals(this.attrSpec.getAttrTmpl().getJavaCode())) {
                return this.attrSpec.getAttrTmpl();
            } else {
                return AttrExt.getAttrTmplByTypeCode(this.attrSpec.getAttrTmpl().getAttrTmplList(),
                    displayType, javaCode);
            }
        }
        return null;
    }
    
    /**
     * 根据类型和code获取指定的模板配置.
     * 
     * @param attrTmplList List<AttrTmpl>
     * @param displayType String
     * @param javaCode String
     * @return void
     */
    public static AttrTmpl getAttrTmplByTypeCode(final List<AttrTmpl> attrTmplList,
        final String displayType, final String javaCode) {
        if (attrTmplList != null) {
            for (final AttrTmpl attrTmpl : attrTmplList) {
                if (attrTmpl != null) {
                    if (("" + displayType).equals(attrTmpl.getDisplayMode())
                        && ("" + javaCode).equals(attrTmpl.getJavaCode())) { // 自己
                        return attrTmpl;
                    }
                    final AttrTmpl subRet = AttrExt.getAttrTmplByTypeCode(attrTmpl
                        .getAttrTmplList(), displayType, javaCode);
                    if (subRet != null) { // 下级
                        return subRet;
                    }
                }
            }
        }
        return null;
    }
    
    /**
     * refreshButtonText.
     * 
     * @author wuyx
     * 2011-3-24 wuyx 
     */
    public void refreshButtonText() {
        final Component comp = this.attrContainer.getFirstChild();
        if (comp != null) {
            AttrCompFactory.getInstByComponent(comp).refreshButtonText(this, comp, null);
        }
    }
    
    /**
     * 注册监听.
     * 
     * @param key String
     * @param evtCallback EvtCallback
     * @author wuyx
     * 2011-4-11 wuyx 
     */
    public void registerEvtCallback(String key, EvtCallback evtCallback) {
        if (this.refreshEvtCallback == null) {
            this.refreshEvtCallback.put(key, evtCallback);
        }
    };
    
    /**
     * 清空册监听.
     * 
     * @author wuyx
     * 2011-4-11 wuyx 
     */
    public void clearRefreshEventListener() {
        if (this.refreshEvtCallback != null) {
            this.refreshEvtCallback.clear();
        }
    };
    
    /**
     * 设置信息是否可见.
     * @param attrViewMap 信息是否可见映照
     */
    /*
    public void setHideValue(Map<String, Boolean> attrViewMap) {
     if (attrViewMap != null && attrViewMap.size() > 0) {
         final Component comp = this.attrContainer.getFirstChild();
         AttrCompFactory.getInstByComponent(comp).setHideValue(comp, attrViewMap);
     }
    }*/
    /**
     * 设置信息显示控制.
     * @param attrViewMap 信息是否可见映照
     */
    public void setAttrView(Map<String, Integer> attrViewMap) {
        if (attrViewMap != null && attrViewMap.size() > 0) {
            final Component comp = this.attrContainer.getFirstChild();
            AttrCompFactory.getInstByComponent(comp).setAttrView(comp, attrViewMap);
        }
    }
    
    /**
     * 设置信息约束控制.
     * @param attrViewMap 
     */
    public void setAttrConstrain(Map<Object, String> attrConstrainMap) {
        if (attrConstrainMap != null && attrConstrainMap.size() > 0) {
            final Component comp = this.attrContainer.getFirstChild();
            AttrCompFactory.getInstByComponent(comp).setAttrConstrain(comp, attrConstrainMap);
        }
    }
    
    /**
     * getAttrBus.
     * 
     * @return AttrBus
     * @author wuyx
     * 2012-1-4 wuyx 
     */
    public AttrBus getAttrBus() {
        if (this.attrBus == null) {
            this.attrBus = new AttrBusImpl();
            this.attrBus.setAttrExt(this);
        }
        return this.attrBus;
    }
    
    /**
     * .
     * 
     * @param attrBus AttrBus
     * @author wuyx
     * 2012-1-17 wuyx 
     */
    public void setAttrBus(AttrBus attrBus) {
        this.attrBus = attrBus;
        if (this.attrBus != null) {
            this.attrBus.setAttrExt(this);
        }
    }
    
}
